#include "CallInfo.h"

namespace qwtapi
{

CallInfo::CallInfo(HCALL hCall)
    : m_hCall(hCall), m_pCallInfo(NULL)
{
    Q_ASSERT(NULL != hCall);
}

CallInfo::~CallInfo()
{
    if (m_pCallInfo)
    {
        free(m_pCallInfo);
        m_pCallInfo = NULL;
    }
}

LONG CallInfo::refresh()
{
    // If we have no call handle, exit.
    if (NULL == m_hCall)
        return LINEERR_UNINITIALIZED;

    // Allocate a buffer for the call information
    DWORD dwSize = m_pCallInfo ? m_pCallInfo->dwTotalSize : sizeof(LINECALLINFO) + 1024;
    for (int i = 0; i < 10; i++)
    {   
        // Allocate it if necessary.  We try to not allocate everytime.
        if (!m_pCallInfo)
        {
            m_pCallInfo = reinterpret_cast<LPLINECALLINFO>(calloc(1, dwSize));
            if (m_pCallInfo == NULL)
                return LINEERR_NOMEM;
        }

        // Mark the size we are sending.
        reinterpret_cast<LPVARSTRING>(m_pCallInfo)->dwTotalSize = dwSize;

        LONG errCode = lineGetCallInfo(m_hCall, m_pCallInfo);
        if (0 != errCode)
            return errCode;

        // If we allocated enough memory we clear the part not being used and return without error.
        if (m_pCallInfo->dwNeededSize <= dwSize)
        {
            // TODO: Test if this works: memset(reinterpret_cast<LPBYTE>(m_pCallInfo) + m_pCallInfo->dwUsedSize, 0, dwSize - m_pCallInfo->dwUsedSize);
            return 0;
        }

        // The memory we allocated was too small, so we increase the size and retry.
        dwSize = m_pCallInfo->dwNeededSize;
        free(m_pCallInfo);
        m_pCallInfo = NULL;
    }

    return LINEERR_NOMEM;
}

bool CallInfo::isValid() const
{
    return NULL != m_pCallInfo;
}

DWORD CallInfo::getAddressId() const
{
    return m_pCallInfo->dwAddressID;
}

QString CallInfo::getCallerIdNumber() const
{
    Q_ASSERT(m_pCallInfo);

    if (!(m_pCallInfo->dwCallerIDFlags & LINECALLPARTYID_ADDRESS) || 0 == m_pCallInfo->dwCallerIDSize)
        return "";

    return QString::fromStdWString(reinterpret_cast<LPCWSTR>(reinterpret_cast<LPBYTE>(m_pCallInfo) + m_pCallInfo->dwCallerIDOffset));
}

QString CallInfo::getCallerIdName() const
{
    Q_ASSERT(m_pCallInfo);

    if (!(m_pCallInfo->dwCallerIDFlags & LINECALLPARTYID_NAME) || 0 == m_pCallInfo->dwCallerIDNameSize)
        return "";

    return QString::fromStdWString(reinterpret_cast<LPCWSTR>(reinterpret_cast<LPBYTE>(m_pCallInfo) + m_pCallInfo->dwCallerIDNameOffset));
}

QString CallInfo::getConnectedIdNumber() const
{
    Q_ASSERT(m_pCallInfo);

    if (!(m_pCallInfo->dwConnectedIDFlags & LINECALLPARTYID_ADDRESS) || 0 == m_pCallInfo->dwConnectedIDSize)
        return "";

    return QString::fromStdWString(reinterpret_cast<LPCWSTR>(reinterpret_cast<LPBYTE>(m_pCallInfo) + m_pCallInfo->dwConnectedIDOffset));
}

QString CallInfo::getConnectedIdName() const
{
    Q_ASSERT(m_pCallInfo);

    if (!(m_pCallInfo->dwConnectedIDFlags & LINECALLPARTYID_NAME) || 0 == m_pCallInfo->dwConnectedIDNameSize)
        return "";

    return QString::fromStdWString(reinterpret_cast<LPCWSTR>(reinterpret_cast<LPBYTE>(m_pCallInfo) + m_pCallInfo->dwConnectedIDNameOffset));
}

QString CallInfo::getCalledIdNumber() const
{
    Q_ASSERT(m_pCallInfo);

    if (!(m_pCallInfo->dwCalledIDFlags & LINECALLPARTYID_ADDRESS) || 0 == m_pCallInfo->dwCalledIDSize)
        return "";

    return QString::fromStdWString(reinterpret_cast<LPCWSTR>(reinterpret_cast<LPBYTE>(m_pCallInfo) + m_pCallInfo->dwCalledIDOffset));
}

QString CallInfo::getCalledIdName() const
{
    Q_ASSERT(m_pCallInfo);

    if (!(m_pCallInfo->dwCalledIDFlags & LINECALLPARTYID_NAME) || 0 == m_pCallInfo->dwCalledIDNameSize)
        return "";

    return QString::fromStdWString(reinterpret_cast<LPCWSTR>(reinterpret_cast<LPBYTE>(m_pCallInfo) + m_pCallInfo->dwCalledIDNameOffset));
}

QString CallInfo::getRedirectingIdNumber() const
{
    Q_ASSERT(m_pCallInfo);

    if (!(m_pCallInfo->dwRedirectingIDFlags & LINECALLPARTYID_ADDRESS) || 0 == m_pCallInfo->dwRedirectingIDSize)
        return "";

    return QString::fromStdWString(reinterpret_cast<LPCWSTR>(reinterpret_cast<LPBYTE>(m_pCallInfo) + m_pCallInfo->dwRedirectingIDOffset));
}

QString CallInfo::getRedirectingIdName() const
{
    Q_ASSERT(m_pCallInfo);

    if (!(m_pCallInfo->dwRedirectingIDFlags & LINECALLPARTYID_NAME) || 0 == m_pCallInfo->dwRedirectingIDNameSize)
        return "";

    return QString::fromStdWString(reinterpret_cast<LPCWSTR>(reinterpret_cast<LPBYTE>(m_pCallInfo) + m_pCallInfo->dwRedirectingIDNameOffset));
}

QString CallInfo::getRedirectionIdNumber() const
{
    Q_ASSERT(m_pCallInfo);

    if (!(m_pCallInfo->dwRedirectionIDFlags & LINECALLPARTYID_ADDRESS) || 0 == m_pCallInfo->dwRedirectionIDSize)
        return "";

    return QString::fromStdWString(reinterpret_cast<LPCWSTR>(reinterpret_cast<LPBYTE>(m_pCallInfo) + m_pCallInfo->dwRedirectionIDOffset));
}

QString CallInfo::getRedirectionIdName() const
{
    Q_ASSERT(m_pCallInfo);

    if (!(m_pCallInfo->dwRedirectionIDFlags & LINECALLPARTYID_NAME) || 0 == m_pCallInfo->dwRedirectionIDNameSize)
        return "";

    return QString::fromStdWString(reinterpret_cast<LPCWSTR>(reinterpret_cast<LPBYTE>(m_pCallInfo) + m_pCallInfo->dwRedirectionIDNameOffset));
}

}
